// Starter program for HW 0. 
// Program draws a triangle. Study the program first
// Then modify the function generateGeometry to draw a two-Dimensional Sierpinski Gasket       
// Generated using randomly selected vertices and bisection

// Angel.h is homegrown include file that also includes glew and freeglut

//#define CODING

#ifdef CODING
#include "Angel.h"
//#include <time.h>


// Number of points in polyline
int NumPoints = 0;

//----------------------------------------------------------------------------

// remember to prototype
//void generateGeometry( void );
void initGPUBuffers( void );
void shaderSetup( void );
void display( );
void keyboard( unsigned char key, int x, int y );
void drawPolylineFile(char *FileName);
void myInit(void);
void MyMouse(int button, int state, int x, int y);
void setViewport(GLint x, GLint y, GLint width, GLint ehight);
void random(void);
void setWindow(GLfloat left,GLfloat right,GLfloat bottom,GLfloat top);
void redraw( void);




bool drawmode = FALSE;
bool movemode = FALSE;


typedef vec2 point2;

using namespace std;


// Array for polyline
//const int num = 100;
point2 points[3000];
//point2 drawmodepoints[num];
GLuint program;
GLuint ProjLoc;
int i = 0,j = 0;
float a[100][100],b[100][100];
int m =0,n=0;
int ValueOfm = 0,ValueOfn = 0;

int NumOfPolyLine = 0;
int NumOfpoints[100];


void redraw(void)
{  
	

	glClear(GL_COLOR_BUFFER_BIT);// Clear the screen
	display();
	printf("i = %d",i);
    printf("m = %d n = %d\n",ValueOfm,ValueOfn);
	setViewport(0,0,640,480);
	for(int j = 0; j <= NumOfPolyLine; j++)
	{
		for (int i = 0; i <= NumOfpoints[j]; i++)
		{	printf("points[%d] = point2(%f ,%f)\n",i, (float)a[j][i],480-(float)b[j][i]);
			points[i] = point2( (float)a[j][i] ,480-(float)b[j][i]);
			}
		NumPoints = ValueOfn;
		initGPUBuffers( );
		shaderSetup( );
		setWindow(0, 640, 0,480);
		glDrawArrays( GL_LINE_STRIP, 0, NumOfpoints[j] ); 
	}
	glFlush();
 
}

void MyMouse(int button, int state, int x, int y)
{

	
	if(!drawmode&&!movemode)
	{

		if(state == GLUT_UP&&button ==GLUT_LEFT_BUTTON )
        {	
			glClear(GL_COLOR_BUFFER_BIT);// Clear the screen
			display();
			//printf("x%d y%d\n",x,y);
			setViewport(0,0,640,432);
			if(y<48){
			if (x<64){
				drawPolylineFile( "dino.txt");
			}
			else if(x<64*2){
				drawPolylineFile( "dragon.dat");
			}
			else if(x<64*3){
				drawPolylineFile("house.dat");
			}
			else if(x<64*4){
				drawPolylineFile( "rex.dat");
			}
			else if(x<64*5){
				drawPolylineFile( "scene.dat");
			}
			else if(x<64*6){
				drawPolylineFile( "usa.dat");
			}
			else if(x<64*7){
				drawPolylineFile( "knight.dat");
			}
			else if(x<64*8){
				drawPolylineFile( "birdhead.dat");
			}
			else if(x<64*9){
				drawPolylineFile( "vinci.dat");
			}
			else if(x<64*10){
				
				drawPolylineFile( "vinci.dat");
				
			}
			
			}
        }
	}
	else if(!movemode&&drawmode) {
		if(state == GLUT_DOWN&&button ==GLUT_LEFT_BUTTON )
		{
			setViewport(0,0,640,480);
			// printf("i = %d\n sizeofpoints %d\n",i,sizeof(points));
			 
			
			for(int n= 0;n<=i;n++)
			{   
				if(y<48)
					y =48;
				a[j][i]=(float)x;
				b[j][i]=(float)y;
				points[n]= point2 (a[j][n],480-b[j][n]);
				printf("points[%d]= point2(a[%f],480-b[%f])\n",n,a[n],b[n]);
				
			}
	
			initGPUBuffers( );
			shaderSetup( );
			
			setWindow(0, 640, 0,480);
			
			if(i>0){
				glDrawArrays( GL_LINE_STRIP, 0,i+1 ); 
			}
			i++;
			NumOfPolyLine = j;
			NumOfpoints[NumOfPolyLine] = i;
				
					for(int u=0;u<=NumOfPolyLine;u++)
	{
	printf("-----------\n%d\n",NumOfpoints[u]);
	}
				
			
			glFlush();

		}
	}
	else if(!drawmode&&movemode)
	{	
		if(state == GLUT_DOWN&&button ==GLUT_LEFT_BUTTON ){
			
			
			printf("yes11111111111\n");
			for (m=0;m<100;m++)
			{
				for(n=0;n<100;n++)
				{	//printf("x=%d , y=%d\n",abs((int)a[m][n]-x),abs((int)b[m][n]-y));
					if(abs((int)a[m][n]-x)<10&&abs((int)b[m][n]-y)<10)
					{
					printf("yes\n");
					
					ValueOfm = m;
					ValueOfn = n;
					
					 printf("m = %d n = %d",ValueOfm,ValueOfn);
					break;
					}
					
				}

			}
		}
		if(state == GLUT_UP&&button ==GLUT_LEFT_BUTTON )
		{
	    printf("m = %d n = %d\n-----------\n",ValueOfm,ValueOfn);
		printf("x=%d , y=%d\n",x,y);
		a[ValueOfm][ValueOfn] = x;
		b[ValueOfm][ValueOfn] = y;
		redraw();
		//movemode = FALSE;
		}
	}
}

void setWindow(GLfloat left,GLfloat right,GLfloat bottom,GLfloat top)
{
	
	ProjLoc = glGetUniformLocation( program, "Proj" );
	mat4 ortho = Ortho2D( left, right, bottom, top );
    glUniformMatrix4fv( ProjLoc, 1, GL_FALSE, ortho );
}

void setViewport(GLint x, GLint y, GLint width, GLint ehight)
{
	glViewport(x,y,width,ehight);
}


void myInit(void)
{
	glClearColor( 1.0, 1.0, 1.0, 1.0 );
	glClear(GL_COLOR_BUFFER_BIT);// Clear the screen
}

void drawPolylineFile(char *FileName)
{
	char line[256];
	float left, right, bottom, top;//char *fileName = "dino.txt";
	FILE *inStream;
	if((inStream = fopen(FileName, "rt")) == NULL) // Open The File
	{
		printf("no such file exist!");
		exit(0);
	}



	if(strcmp(FileName,"dino.txt")==0){
	left = 0;
	right = 640;
	bottom = 0;
	top = 480;
	}


	else {
		while(!feof(inStream))
		 {
			 memset(line, 0, 256);
			  fscanf(inStream, "%s", line);
				if(line[0] == '*')
					 break;
				 else
					 continue;
		  }
		
   
    // read in the four directions of extents
		 fscanf(inStream, "%f %f %f %f\n", &left, &top, &right, &bottom);
	//glClear(GL_COLOR_BUFFER_BIT);// Clear the screen
	 }
	GLint numpolys, numLines; 
	GLfloat	x, y;

	fscanf(inStream,"%d", &numpolys);			// read the number of polylines
	for(int j = 0; j < numpolys; j++)
	{	//read each polyline
		
		fscanf(inStream,"%d", &numLines);
		

	
		for (int i = 0; i < numLines; i++)
		{
			fscanf(inStream,"%f %f", &x, &y);
			points[i] = point2( x , y);
			
			
			
		}
		NumPoints = numLines;
		initGPUBuffers( );
		shaderSetup( );
		setWindow(left, right, bottom,top);
		glDrawArrays( GL_LINE_STRIP, 0, NumPoints ); 

		
		
	}
	glFlush();
	fclose(inStream);
}




void initGPUBuffers( void )
{
	    // Create a vertex array object
    GLuint vao;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    // Create and initialize a buffer object
    GLuint buffer;
    glGenBuffers( 1, &buffer );
    glBindBuffer( GL_ARRAY_BUFFER, buffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW );


}


void shaderSetup( void )
{
	    // Load shaders and use the resulting shader program
    program = InitShader( "vshader1.glsl", "fshader1.glsl" );
    glUseProgram( program );

    // Initialize the vertex position attribute from the vertex shader
    GLuint loc = glGetAttribLocation( program, "vPosition" );
    glEnableVertexAttribArray( loc );
    glVertexAttribPointer( loc, 2, GL_FLOAT, GL_FALSE, 0,
                           BUFFER_OFFSET(0) );

	// sets the default color to clear screen
    glClearColor( 1.0, 1.0, 1.0, 1.0 ); // white background

}



//----------------------------------------------------------------------------
// this is where the drawing should happen
void display( )
{
	// TIP 1: remember to enable depth buffering when drawing in 3d

	// TIP 2: If you want to be sure your math functions are right, 
	// prototype your operations in Matlab or Mathematica first to verify correct behavior
	// both programs support some sort of runtime interface to C++ programs

	// TIP3: check your graphics specs. you have a limited number of loop iterations, storage, registers, texture space etc.
	

	// TIP4: avoid using glTranslatex, glRotatex, push and pop
	// pass your own view matrix to the shader directly
	// refer to the latest OpenGL documentation for implementation details

  //  glClear( GL_COLOR_BUFFER_BIT );     // clear the window
  //  glDrawArrays( GL_LINE_STRIP, 0, NumPoints );    // draw the points
  //  glFlush(); // force output to graphics hardware
	int i=0;
	
	
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "dino.txt");
	i++;
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "dragon.dat");
	i++;
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "house.dat");
	i++;
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "rex.dat");
	i++;
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "scene.dat");
	i++;
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "usa.dat");
	i++;
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "knight.dat");
	i++;
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "birdhead.dat");
	i++;
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "vinci.dat");
	i++;
	setViewport(64*i,432 , 64 , 48);
	drawPolylineFile( "vinci.dat");
}

//----------------------------------------------------------------------------
void random(void)
{
	int p;
		
		
		p = rand()%10;
			if (p==0){
				drawPolylineFile( "dino.txt");
			}
			else if(p==1){
				drawPolylineFile( "dragon.dat");
			}
			else if(p==2){
				drawPolylineFile("house.dat");
			}
			else if(p==3){
				drawPolylineFile( "rex.dat");
			}
			else if(p==4){
				drawPolylineFile( "scene.dat");
			}
			else if(p==5){
				drawPolylineFile( "usa.dat");
			}
			else if(p==6){
				drawPolylineFile( "knight.dat");
			}
			else if(p==7){
				drawPolylineFile( "birdhead.dat");
			}
			else if(p==8){
				drawPolylineFile( "vinci.dat");
			}
			else if(p==9){
				drawPolylineFile( "vinci.dat");
			}
}
// keyboard handler
void
keyboard( unsigned char key, int x, int y )
{
    switch ( key ) {
    case 033:
        exit( EXIT_SUCCESS );
        break;
	case 'p':
		drawmode = FALSE;
		glClear(GL_COLOR_BUFFER_BIT);// Clear the screen
		display();
		setViewport(10,10,600,432);
		random();
		break;
	case 't':
		drawmode = FALSE;
		glClear(GL_COLOR_BUFFER_BIT);// Clear the screen
		display();
		int w,h;
		for (w =0;w<6;w++)
		{
			for(h = 0; h < 6; h++){
				setViewport(w*640/6,h*432/6,64,48);
				random();
			}
		}
		break;
	case 'e':
		glClear(GL_COLOR_BUFFER_BIT);// Clear the screen
		display();
		drawmode = TRUE;
		break;

	case'b':
		//ReSetPoints = TRUE;
		i=0;
		j++;
		break;
	case'm':
		drawmode = FALSE;
		movemode = TRUE;
		break;

    }
}

//----------------------------------------------------------------------------
// entry point
int
main( int argc, char **argv )
{
	// init glut
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_SINGLE );
    glutInitWindowSize( 640, 480 );

    // If you are using freeglut, the next two lines will check if 
    // the code is truly 3.2. Otherwise, comment them out
    
   // glutInitContextVersion( 3, 3 );
  //  glutInitContextProfile( GLUT_CORE_PROFILE );

	// create GLUT window for drawing
    glutCreateWindow( "Starting App" );

	// init glew
    glewInit();
	 
  
	// assign handlers
	myInit();
    glutDisplayFunc( display );
    glutKeyboardFunc( keyboard );
	glutMouseFunc(MyMouse);
	// should add menus
	// add mouse handler
	// add resize window functionality (should probably try to preserve aspect ratio)

	// enter the drawing loop
	// frame rate can be controlled with 
    glutMainLoop();
    return 0;
}
#else
#endif
